/*
 * $Id: string_strtok.c,v 1.5 2006-08-30 14:27:09 bacon Exp $
 */

#if defined(__MSTRING)
#include <xp/bas/mstring.h>
#elif defined(__WSTRING)
#include <xp/bas/wstring.h>
#else
#include <xp/bas/string.h>
#endif
#include <xp/bas/ctype.h>

xp_char_t* xp_strtok (const xp_char_t* s, 
	const xp_char_t* delim, xp_char_t** tok, xp_size_t* tok_len)
{
	const xp_char_t* p = s, *d;
	const xp_char_t* sp = XP_NULL, * ep = XP_NULL;
	xp_char_t c; 
	int delim_mode;

	/* skip preceding space xp_char_tacters */
	while (/* *p != XP_CHAR('\0') && */ xp_isspace(*p)) p++;

	if (delim == XP_NULL) delim_mode = 0;
	else {
		delim_mode = 1;
		for (d = delim; *d != XP_CHAR('\0'); d++) 
			if (!xp_isspace(*d)) delim_mode = 2;
	}

	if (delim_mode == 0) { 
		/* when XP_NULL is given as "delim", it has an effect of cutting
		   preceding and trailing space characters off "s". */
		while ((c = *p) != XP_CHAR('\0')) {
			if (!xp_isspace(c)) {
				if (sp == XP_NULL) sp = p;
				ep = p;
			}
			p++;
		}
	}
	else if (delim_mode == 1) {
		while ((c = *p) != XP_CHAR('\0')) {
			if (xp_isspace(c)) break;

			if (sp == XP_NULL) sp = p;
			ep = p++;
		}
	}
	else { /* if (delim_mode == 2) { */
		while ((c = *p) != XP_CHAR('\0')) {
			if (xp_isspace(c)) {
				p++;
				continue;
			}
			for (d = delim; *d; d++) {
				if (c == *d) {
					goto exit_loop;
				}
			}
			if (sp == XP_NULL) sp = p;
			ep = p++;
		}
	}

exit_loop:
	if (sp == XP_NULL) {
		*tok = XP_NULL;
		*tok_len = (xp_size_t)0;
	}
	else {
		*tok = (xp_char_t*)sp;
		*tok_len = ep - sp + 1;
	}
	return (c == XP_CHAR('\0'))? XP_NULL: ((xp_char_t*)++p);
}

xp_char_t* xp_strxtok (const xp_char_t* s, xp_size_t len,
	const xp_char_t* delim, xp_char_t** tok, xp_size_t* tok_len)
{
	const xp_char_t* p = s, *d;
	const xp_char_t* end = s + len;	
	const xp_char_t* sp = XP_NULL, * ep = XP_NULL;
	xp_char_t c; 
	int delim_mode;

	/* skip preceding space xp_char_tacters */
	while (p < end && xp_isspace(*p)) p++;

	if (delim == XP_NULL) delim_mode = 0;
	else {
		delim_mode = 1;
		for (d = delim; *d != XP_CHAR('\0'); d++) 
			if (!xp_isspace(*d)) delim_mode = 2;
	}

	if (delim_mode == 0) { 
		/* when XP_NULL is given as "delim", it has an effect of cutting
		   preceding and trailing space xp_char_tacters off "s". */
		while (p < end) {
			c = *p;
			if (!xp_isspace(c)) {
				if (sp == XP_NULL) sp = p;
				ep = p;
			}
			p++;
		}
	}
	else if (delim_mode == 1) {
		while (p < end) {
			c = *p;
			if (xp_isspace(c)) break;
			if (sp == XP_NULL) sp = p;
			ep = p++;
		}
	}
	else { /* if (delim_mode == 2) { */
		while (p < end) {
			c = *p;
			if (xp_isspace(c)) {
				p++;
				continue;
			}
			for (d = delim; *d; d++) {
				if (c == *d) {
					goto exit_loop;
				}
			}
			if (sp == XP_NULL) sp = p;
			ep = p++;
		}
	}

exit_loop:
	if (sp == XP_NULL) {
		*tok = XP_NULL;
		*tok_len = (xp_size_t)0;
	}
	else {
		*tok = (xp_char_t*)sp;
		*tok_len = ep - sp + 1;
	}

	return (p >= end)? XP_NULL: ((xp_char_t*)++p);
}

xp_char_t* xp_strxntok (
	const xp_char_t* s, xp_size_t len,
	const xp_char_t* delim, xp_size_t delim_len, 
	xp_char_t** tok, xp_size_t* tok_len)
{
	const xp_char_t* p = s, *d;
	const xp_char_t* end = s + len;	
	const xp_char_t* sp = XP_NULL, * ep = XP_NULL;
	const xp_char_t* delim_end = delim + delim_len;
	xp_char_t c; 
	int delim_mode;

	/* skip preceding space xp_char_tacters */
	while (p < end && xp_isspace(*p)) p++;

	if (delim == XP_NULL) delim_mode = 0;
	else 
	{
		delim_mode = 1;
		for (d = delim; d < delim_end; d++) 
			if (!xp_isspace(*d)) delim_mode = 2;
	}

	if (delim_mode == 0) 
	{ 
		/* when XP_NULL is given as "delim", it has an effect of cutting
		   preceding and trailing space xp_char_tacters off "s". */
		while (p < end) 
		{
			c = *p;

			if (!xp_isspace(c)) 
			{
				if (sp == XP_NULL) sp = p;
				ep = p;
			}
			p++;
		}
	}
	else if (delim_mode == 1) 
	{
		while (p < end) 
		{
			c = *p;
			if (xp_isspace(c)) break;
			if (sp == XP_NULL) sp = p;
			ep = p++;
		}
	}
	else /* if (delim_mode == 2) */ 
	{
		while (p < end) 
		{
			c = *p;
			if (xp_isspace(c)) 
			{
				p++;
				continue;
			}
			for (d = delim; d < delim_end; d++) 
			{
				if (c == *d) goto exit_loop;
			}
			if (sp == XP_NULL) sp = p;
			ep = p++;
		}
	}

exit_loop:
	if (sp == XP_NULL) 
	{
		*tok = XP_NULL;
		*tok_len = (xp_size_t)0;
	}
	else 
	{
		*tok = (xp_char_t*)sp;
		*tok_len = ep - sp + 1;
	}

	return (p >= end)? XP_NULL: ((xp_char_t*)++p);
}

